home *** CD-ROM | disk | FTP | other *** search
- #include "alloc.h"
- #include "debugger.h"
- #include "gc.h"
- #include "gc_ctrl.h"
- #include "major_gc.h"
- #include "minor_gc.h"
- #include "mlvalues.h"
-
- long stat_minor_words = 0,
- stat_promoted_words = 0,
- stat_major_words = 0,
- stat_minor_collections = 0,
- stat_major_collections = 0,
- stat_heap_size = 0; /* bytes */
-
- extern asize_t major_heap_increment; /* bytes; cf. major_gc.c */
- extern int percent_free; /* cf. major_gc.c */
- extern int verb_gc; /* cf. misc.c */
-
- #define Chunk_size(c) (((heap_chunk_head *) (c)) [-1]).size
- #define Chunk_next(c) (((heap_chunk_head *) (c)) [-1]).next
- #define Next(hp) ((hp) + Bhsize_hp (hp))
-
- /* This will also thoroughly verify the heap if compiled in DEBUG mode. */
-
- value gc_stat (v) /* ML */
- value v;
- {
- value res;
- long live_words = 0, live_blocks = 0,
- free_words = 0, free_blocks = 0, largest_free = 0,
- fragments = 0, heap_chunks = 0;
- char *chunk = heap_start, *chunk_end;
- char *cur_hp, *prev_hp;
- header_t cur_hd;
-
- Assert (v == Atom (0));
-
- while (chunk != NULL){
- ++ heap_chunks;
- chunk_end = chunk + Chunk_size (chunk);
- prev_hp = NULL;
- cur_hp = chunk;
- while (cur_hp < chunk_end){
- cur_hd = Hd_hp (cur_hp);
- switch (Color_hd (cur_hd)){
- case White:
- if (Wosize_hd (cur_hd) == 0){
- ++fragments;
- Assert (prev_hp == NULL
- || (Color_hp (prev_hp) != Blue
- && Wosize_hp (prev_hp) > 0));
- Assert (Next (cur_hp) == chunk_end
- || (Color_hp (Next (cur_hp)) != Blue
- && Wosize_hp (Next (cur_hp)) > 0));
- break;
- }
- /* FALLTHROUGH */
- case Gray: case Black:
- Assert (Wosize_hd (cur_hd) > 0);
- ++ live_blocks;
- live_words += Whsize_hd (cur_hd);
- break;
- case Blue:
- Assert (Wosize_hd (cur_hd) > 0);
- ++ free_blocks;
- free_words += Whsize_hd (cur_hd);
- if (Whsize_hd (cur_hd) > largest_free){
- largest_free = Whsize_hd (cur_hd);
- }
- Assert (prev_hp == NULL
- || (Color_hp (prev_hp) != Blue
- && Wosize_hp (prev_hp) > 0));
- Assert (Next (cur_hp) == chunk_end
- || (Color_hp (Next (cur_hp)) != Blue
- && Wosize_hp (Next (cur_hp)) > 0));
- break;
- }
- prev_hp = cur_hp;
- cur_hp = Next (cur_hp);
- } Assert (cur_hp == chunk_end);
- chunk = Chunk_next (chunk);
- }
-
- Assert (live_words + free_words + fragments == Wsize_bsize (stat_heap_size));
- /* Order of elements changed for Moscow ML */
- res = alloc (13, 0);
- Field (res, 11) = Val_long (stat_minor_words
- + Wsize_bsize (young_ptr - young_start));
- Field (res, 12) = Val_long (stat_promoted_words);
- Field (res, 9) = Val_long (stat_major_words + allocated_words);
- Field (res, 10) = Val_long (stat_minor_collections);
- Field (res, 8) = Val_long (stat_major_collections);
- Field (res, 4) = Val_long (Wsize_bsize (stat_heap_size));
- Field (res, 3) = Val_long (heap_chunks);
- Field (res, 7) = Val_long (live_words);
- Field (res, 6) = Val_long (live_blocks);
- Field (res, 2) = Val_long (free_words);
- Field (res, 1) = Val_long (free_blocks);
- Field (res, 5) = Val_long (largest_free);
- Field (res, 0) = Val_long (fragments);
- return res;
- }
-
- value gc_get (v) /* ML */
- value v;
- {
- value res;
-
- Assert (v == Atom (0));
- /* Order of elements changed for Moscow ML */
- res = alloc (4, 0);
- Field (res, 1) = Wsize_bsize (Val_long (minor_heap_size));
- Field (res, 0) = Wsize_bsize (Val_long (major_heap_increment));
- Field (res, 2) = Val_long (percent_free);
- Field (res, 3) = Val_bool (verb_gc);
- return res;
- }
-
- static int norm_pfree (p)
- int p;
- {
- if (p < 1) return p = 1;
- return p;
- }
-
- static long norm_heapincr (i)
- long i;
- {
- i = ((i + (1 << Page_log) - 1) >> Page_log) << Page_log;
- if (i < Heap_chunk_min) i = Heap_chunk_min;
- if (i > Heap_chunk_max) i = Heap_chunk_max;
- return i;
- }
-
- static long norm_minsize (s)
- long s;
- {
- if (s < Minor_heap_min) s = Minor_heap_min;
- if (s > Minor_heap_max) s = Minor_heap_max;
- return s;
- }
-
- value gc_set (v) /* ML */
- value v;
- {
- int newpf;
- /* Order of elements changed for Moscow ML */
- verb_gc = Bool_val (Field (v, 3));
-
- newpf = norm_pfree (Long_val (Field (v, 2)));
- if (newpf != percent_free){
- percent_free = newpf;
- gc_message ("New space overhead: %d%%\n", percent_free);
- }
-
- if (Bsize_wsize (Long_val (Field (v, 0))) != major_heap_increment){
- major_heap_increment = norm_heapincr (Bsize_wsize (Long_val (Field(v,0))));
- gc_message ("New heap increment size: %ldk\n", major_heap_increment/1024);
- }
-
- /* Minor heap size comes last because it will trigger a minor collection
- (thus invalidating [v]) and it can raise [Out_of_memory]. */
- if (Bsize_wsize (Long_val (Field (v, 1))) != minor_heap_size){
- long new_size = norm_minsize (Bsize_wsize (Long_val (Field (v, 1))));
- gc_message ("New minor heap size: %ldk\n", new_size/1024);
- set_minor_heap_size (new_size);
- }
- return Atom (0);
- }
-
- value gc_minor (v) /* ML */
- value v;
- { Assert (v == Atom (0));
- minor_collection ();
- return Atom (0);
- }
-
- value gc_major (v) /* ML */
- value v;
- { Assert (v == Atom (0));
- minor_collection ();
- finish_major_cycle ();
- return Atom (0);
- }
-
- value gc_full_major (v) /* ML */
- value v;
- { Assert (v == Atom (0));
- minor_collection ();
- finish_major_cycle ();
- finish_major_cycle ();
- return Atom (0);
- }
-
- void init_gc (minor_size, major_incr, percent_fr, verb)
- long minor_size;
- long major_incr;
- int percent_fr;
- int verb;
- {
- #ifdef DEBUG
- gc_message ("*** camlrunm: debug mode ***\n", 0);
- #endif
- verb_gc = verb;
- set_minor_heap_size (Bsize_wsize (norm_minsize (minor_size)));
- major_heap_increment = Bsize_wsize (norm_heapincr (major_incr));
- percent_free = norm_pfree (percent_fr);
- init_major_heap (major_heap_increment);
- init_c_roots ();
- gc_message ("Initial space overhead: %d%%\n", percent_free);
- gc_message ("Initial heap increment: %ldk\n", major_heap_increment / 1024);
- gc_message ("Initial minor heap size: %ldk\n", minor_heap_size / 1024);
- }
-